﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace DownloadTED
{
	public partial class DownloadSubtitlesByURLs : Form
	{
		public DownloadSubtitlesByURLs()
		{
			InitializeComponent();

			AdvancedLanguagesCheckBox.Checked = false;
			LanguagesTextBox.Visible = AdvancedLanguagesCheckBox.Checked;
			SelectedLanguagesComboBox.Visible = !AdvancedLanguagesCheckBox.Checked;
			RemoveSelectedLanguageButton.Visible = !AdvancedLanguagesCheckBox.Checked;
			AvailableLanguagesComboBox.Visible = !AdvancedLanguagesCheckBox.Checked;
			AddAvailableLanguageButton.Visible = !AdvancedLanguagesCheckBox.Checked;
		}

		public enum DownloadMethods
		{
			FirstDetected,
			AllSpecified,
			AllAvailable,
		}

		private void DownloadButton_Click(object sender, System.EventArgs e)
		{
			if (folderBrowserDialog1.ShowDialog() != System.Windows.Forms.DialogResult.OK)
				return;
			DownloadMethods method=  (DownloadMethods)DownloadMethodComboBox.SelectedIndex;
			switch (method) {
				case DownloadMethods.AllAvailable:
					break;
				case DownloadMethods.FirstDetected:
				case DownloadMethods.AllSpecified:
					if ((AdvancedLanguagesCheckBox.Checked && string.IsNullOrEmpty(LanguagesTextBox.Text)) || SelectedLanguagesComboBox.Items.Count == 0) {
						MessageBox.Show("Please select which subtitles you want to download");
						return;
					}
					break;
				default:
					MessageBox.Show("Please select which subtitles you want to download");
					return;
			}

			List<string> urls=new List<string>();
			foreach (string url in URLsTextBox.Text.Split('\r', '\n').Where(p => string.IsNullOrEmpty(p) == false))
				urls.Add(url);
			List<string> languages=new List<string>();
			if (AdvancedLanguagesCheckBox.Checked) {
				foreach (Match lang in Regex.Matches(LanguagesTextBox.Text, "\\w{3}"))
					languages.Add(lang.Value);
			} else {
				foreach (string item in SelectedLanguagesComboBox.Items)
					languages.Add(item);
			}

			string srt=null;
			foreach (string url in urls) {
				TedVideo tedVideo=TedUtility.Create(url);
				switch (method) {
					case DownloadMethods.FirstDetected:
						string lang1=languages.Single(p => tedVideo.Languages.Contains(p));
						if (string.IsNullOrEmpty(lang1))
							continue;
						srt = GetSubtitle(tedVideo, lang1);
						if (string.IsNullOrEmpty(srt))
							continue;
						File.WriteAllText(GenerateFileName(folderBrowserDialog1.SelectedPath, tedVideo, lang1), srt);
						break;
					case DownloadMethods.AllSpecified:
						foreach (string lang2 in languages) {
							srt = GetSubtitle(tedVideo, lang2);
							if (string.IsNullOrEmpty(srt))
								continue;

							File.WriteAllText(GenerateFileName(folderBrowserDialog1.SelectedPath, tedVideo, lang2), srt);
						}
						break;
					case DownloadMethods.AllAvailable:
						foreach (string lang3 in tedVideo.Languages) {
							srt = GetSubtitle(tedVideo, lang3);
							if (string.IsNullOrEmpty(srt))
								continue;

							File.WriteAllText(GenerateFileName(folderBrowserDialog1.SelectedPath, tedVideo, lang3), srt);
						}
						break;
					default:
						break;
				}
			}

			MessageBox.Show("All subtitles downloaded");
		}

		private string GenerateFileName(string path, TedVideo video, string lang)
		{
			string fileName = path + "\\" + (NamingTypeComboBox.SelectedIndex == 0 ? video.Code + "-" + lang + ".srt" : Path.GetFileNameWithoutExtension(video.VideoHighQualityUrl) + "." + lang + ".srt");
			int count = 0;
			while (File.Exists(fileName))
				fileName = path + "\\" + (NamingTypeComboBox.SelectedIndex == 0 ? video.Code + "-" + lang + "-" + (count++) + ".srt" : Path.GetFileNameWithoutExtension(video.VideoHighQualityUrl) + "." + lang + "-" + (count++) + ".srt");

			return fileName;
		}

		private string GetSubtitle(TedVideo tedVideo, string lang)
		{
			string subtitleUrl=string.Format("http://www.ted.com/talks/subtitles/id/{0}/lang/{1}", tedVideo.Code, lang);
			string subtitleValue=TedUtility.GetHttpHtml(subtitleUrl).Replace("\\\"", "&quot;");
			string p1=@"\""content\""\:\""(?<content>[^\""]*)\"",";
			string p2=@"\""startTime\""\:(?<startTime>\d+),";
			string p3=@"\""duration\""\:(?<duration>\d+),";
			string p4=@"\""startOfParagraph\""\:(?<startOfParagraph>\w+)";
			int count=1; string validSubtitle=null;

			MatchCollection matches=Regex.Matches(subtitleValue, p1 + p2 + p3 + p4);
			if (matches.Count == 0)
				return null;
			foreach (Match match in matches) {
				validSubtitle += string.Format(
					"{0}\n{1} --> {2}\n{3}\n\n",
					count++,
					SubtitleTime(tedVideo.IntroDuration + int.Parse(match.Groups["startTime"].Value)),
					SubtitleTime(tedVideo.IntroDuration + int.Parse(match.Groups["startTime"].Value) + int.Parse(match.Groups["duration"].Value)),
					match.Groups["content"].Value
				);
			}

			return validSubtitle;
		}

		private string SubtitleTime(int val)
		{
			int mils = val % 1000;
			int segs = (val / 1000) % 60;
			int mins = (val / 60000) % 60;
			int hors = (val / 3600000);
			return string.Format(
				"{0}:{1}:{2},{3}",
				Prefixed(hors.ToString(), 2, "0"),
				Prefixed(mins.ToString(), 2, "0"),
				Prefixed(segs.ToString(), 2, "0"),
				Prefixed(mils.ToString(), 3, "0")
			);
		}

		private string Prefixed(string value, int length, string c)
		{
			if (value.Length >= length)
				return value;
			for (int i = 0; i < length - value.Length; i++)
				value = c + value;
			return value;
		}

		private void AddAvailableLanguageButton_Click(object sender, System.EventArgs e)
		{
			SelectedLanguagesComboBox.Items.Add(AvailableLanguagesComboBox.SelectedItem);
			SelectedLanguagesComboBox.SelectedItem = AvailableLanguagesComboBox.SelectedItem;
			AvailableLanguagesComboBox.Items.Remove(AvailableLanguagesComboBox.SelectedItem);
			AvailableLanguagesComboBox.SelectedIndex = 0;
		}

		private void RemoveSelectedLanguageButton_Click(object sender, System.EventArgs e)
		{
			AvailableLanguagesComboBox.Items.Add(SelectedLanguagesComboBox.SelectedItem);
			AvailableLanguagesComboBox.SelectedItem = SelectedLanguagesComboBox.SelectedItem;
			SelectedLanguagesComboBox.Items.Remove(SelectedLanguagesComboBox.SelectedItem);
			SelectedLanguagesComboBox.SelectedIndex = 0;
		}

		private void AdvancedLanguagesCheckBox_CheckedChanged(object sender, System.EventArgs e)
		{
			LanguagesTextBox.Visible = AdvancedLanguagesCheckBox.Checked;
			SelectedLanguagesComboBox.Visible = !AdvancedLanguagesCheckBox.Checked;
			RemoveSelectedLanguageButton.Visible = !AdvancedLanguagesCheckBox.Checked;
			AvailableLanguagesComboBox.Visible = !AdvancedLanguagesCheckBox.Checked;
			AddAvailableLanguageButton.Visible = !AdvancedLanguagesCheckBox.Checked;
		}
	}
}